using LyxWaf.Policy;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
using System.Net;
using System.Text;
using Yarp.ReverseProxy.Configuration;
using Yarp.ReverseProxy.Health;
using LyxWaf.Middleware;
using LyxWaf.Transformer;
using Yarp.ReverseProxy.Transforms;
using LyxWaf.Services.Files;
using Microsoft.AspNetCore.HttpOverrides;
using System.Threading.RateLimiting;
using LyxWaf.Services.SpeedLimit;
using LyxWaf.Services.Statistic;
using LyxWaf.Services;
using LyxWaf.Analysis;
using LyxWaf.Services.Protect;

using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using System.Net.Security;
using LyxWaf.Utils;
using LyxWaf.Services.WafInfo;


using System.CommandLine;
using System.CommandLine.Parsing;
using CommandLine;

// Remote 子命令：添加远程仓库
[Verb("add", HelpText = "添加一个新的远程仓库。")]
public class RemoteAddOptions
{
    [Value(0, MetaName = "name", Required = true, HelpText = "远程仓库的名称。")]
    public string Name { get; set; }

    [Value(1, MetaName = "url", Required = true, HelpText = "远程仓库的URL。")]
    public string Url { get; set; }
}


// Remote 子命令：移除远程仓库
[Verb("remove", HelpText = "移除一个已存在的远程仓库。")]
public class RemoteRemoveOptions
{
    [Value(0, MetaName = "name", Required = true, HelpText = "要移除的远程仓库的名称。")]
    public string Name { get; set; }
}
public class Program
{
    static int Main(string[] args)
    {
        var parserResult = Parser.Default.ParseArguments<RemoteAddOptions, RemoteRemoveOptions>(args);

        return 0;
        Option<bool> versionOption = new("--version")
        {
            Description = "显示应用程序当前版本号"
        };

        Option<bool> xxa = new("--aaa")
        {
            Description = "aaaa"
        };

        RootCommand rootCommand = new("LyxWaf防火墙");
        rootCommand.Options.RemoveAt(1);
        rootCommand.Options.Add(versionOption);
        rootCommand.Options.Add(xxa);

        var file = new Command("file-server", "文件服务器");

        Option<bool> aa = new("--s")
        {
            Description = "显示应用程序当前版本号"
        };
        file.Options.Add(aa);

        rootCommand.Add(file);


        ParseResult parseResult = rootCommand.Parse(args);
        var showVersion = parseResult.GetValue(versionOption);
        if (showVersion)
        {
            Console.WriteLine("当前版本为0.1.0");
            return 0;
        }
        rootCommand.SetAction(parseResult =>
        {
            DoStartWaf(args, parseResult);
            return 0;
        });
        return parseResult.Invoke();
    }

    public static void DoStartWaf(string[] args, ParseResult parseResult)
    {
        var builder = WebApplication.CreateBuilder(args);
        builder.Configuration.AddYamlFile("appsettings.yaml", optional: false, reloadOnChange: true);

        // var xx = builder.Configuration.GetSection("WafInfos");
        // var waf = new WafInfoOptions();
        // waf.Listens.Add(new OneLintenInfo{
        //     Port=5111,
        // });
        // builder.Configuration.AddJsonStream(CommonUtil.ObjectToStream("WafInfos", waf));

        // var xx1 = builder.Configuration.GetSection("WafInfos");

        builder.Services.Configure<WafInfoOptions>(builder.Configuration.GetSection("WafInfos"));
        builder.Services.Configure<ProtectOptions>(builder.Configuration.GetSection("Protect"));
        builder.Services.Configure<SpeedLimitOptions>(builder.Configuration.GetSection("SpeedLimit"));
        builder.Services.Configure<FileProviderOptions>(builder.Configuration.GetSection("FileProvider"));
        builder.Services.Configure<StatisticOptions>(builder.Configuration.GetSection("Statistic"));

        builder.Services.AddMemoryCache();
        builder.Services.AddSingleton<IFileService, FileService>();
        builder.Services.AddSingleton<ISpeedLimitService, SpeedLimitService>();
        builder.Services.AddSingleton<IProtectService, ProtectService>();
        builder.Services.AddSingleton<IStatisticService, StatisticService>();
        builder.Services.AddSingleton<IWafInfoService, WafInfoService>();
        builder.Services.AddSingleton<IProbingRequestFactory, LyxProbingRequestFactory>();
        builder.Services.AddSingleton<IActiveHealthCheckPolicy, LyxActiveHealthPolicy>();

        Analysis.DoStartAnalysis();

        var wafInfos = new WafInfoOptions();
        builder.Configuration.GetSection("WafInfos").Bind(wafInfos);
        wafInfos.Init();
        builder.WebHost.UseKestrel((context, options) =>
        {
            foreach (var url in wafInfos.Listens)
            {
                if (url.IsHttps)
                {
                    options.Listen(IPAddress.Parse(url.Host), url.Port, listenOptions =>
                    {
                        listenOptions.UseHttps(new TlsHandshakeCallbackOptions
                        {
                            OnConnection = context =>
                            {
                                var services = ServiceLocator.GetRequiredService<IWafInfoService>() ?? throw new Exception("HTTPS证书暂未加载");
                                var name = context.ClientHelloInfo.ServerName;
                                var cert = services.GetCertByName(name);
                                return new ValueTask<SslServerAuthenticationOptions>(new SslServerAuthenticationOptions
                                {
                                    ServerCertificate = cert
                                });
                            },
                        });
                    });
                }
                else
                {
                    options.Listen(IPAddress.Parse(url.Host), url.Port);
                }
            }
        });


        builder.Services.AddReverseProxy()
            .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
            .ConfigureHttpClient((context, handler) =>
            {
                handler.SslOptions.EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
                // handler.SslOptions.RemoteCertificateValidationCallback = (message, cert, chain, sslPolicyErrors) =>
                // {
                //     Console.Write($"fff{message}");
                //     return true;
                // };
                // handler.SslOptions.LocalCertificateSelectionCallback = (message, cert, chain, sslPolicyErrors, a) =>
                // {
                //     X509Certificate2 clientCert = X509Certificate2.CreateFromPemFile(".well-known/pri_key.pem", ".well-known/pri_key.pem.key");
                //     Console.Write($"fff{message}");
                //     return clientCert;
                // };

            }).AddTransforms<DestinationTrans>();

        var app = builder.Build();
        var logger1 = app.Services.GetRequiredService<ILogger<Program>>();
        logger1.LogInformation("YARP应用启动中...");
        app.MapReverseProxy(proxyApp =>
        {
            proxyApp.UseMiddleware<WafControlMiddleware>();
            proxyApp.UseMiddleware<StatisticLogMiddleware>();
            proxyApp.UseMiddleware<ThrottledMiddleware>();
            proxyApp.UseMiddleware<SpeedLimitMiddleware>();
            proxyApp.UseMiddleware<FileProviderMiddleware>();
        });
        app.Run();
    }
}
// var logger = LoggerFactory.Create(builder => builder.AddNLog()).CreateLogger<Program>();
// logger.LogInformation("Program has started.");
